package cathttp

import (
	"time"
)

// Time 执行时间
var Time int64

// CycleParam 周期参数
type CycleParam struct {
	Stop bool   // 停止标记
	Time int64  // 超时时间(毫秒)
	Call func() // 回调
	// 剩余时间 (毫秒)
	surplusTime int64
}

// Cycle 周期
var Cycle struct {
	N        int64
	Queue    map[int64]*CycleParam
	Add      func(Time int64, Call func()) int64
	Delete   func(ID int64) bool
	SetStop  func(ID int64, Stop bool) bool
	GetState func(ID int64) bool
}

// init 初始化
func init() {
	Cycle.Queue = make(map[int64]*CycleParam)
	// ! 增加锁保证在协程中可以正常写
	lock := make(chan bool, 1)
	// * Add 添加 返回定时器 ID
	// Time 超时时间 (毫秒)
	// Call 触发函数
	Cycle.Add = func(Time int64, Call func()) int64 {
		lock <- false
		N := Cycle.N + 1 // 增加
		Cycle.Queue[N] = &CycleParam{false, Time, Call, Time}
		Cycle.N = N // 赋值
		<-lock
		return N // 返回
	}
	// * Delete 删除
	//	ID   定时器ID
	Cycle.Delete = func(ID int64) bool {
		lock <- false
		if _, ok := Cycle.Queue[ID]; ok {
			delete(Cycle.Queue, ID)
			<-lock
			return true
		}
		<-lock
		return false
	}
	// * SetStop  定时器停止
	//	ID   定时器ID
	//	Stop 定时器状态
	Cycle.SetStop = func(ID int64, Stop bool) bool {
		lock <- false
		if C, ok := Cycle.Queue[ID]; ok {
			C.Stop = Stop
			<-lock
			return true
		}
		<-lock
		return false
	}
	// * GetState 定时器状态
	Cycle.GetState = func(ID int64) bool {
		lock <- false
		if C, ok := Cycle.Queue[ID]; ok {
			<-lock
			return C.Stop
		}
		<-lock
		return false
	}
	ticker := time.NewTicker(time.Millisecond)
	// * 处理
	go func() {
		defer ticker.Stop()
		for {
			// * 一毫秒一周期
			Time = (<-ticker.C).UnixNano() // * 更新全局时间
			lock <- false
			// * 处理时间队列
			for _, T := range Cycle.Queue {
				if !T.Stop {
					T.surplusTime-- // * 时间自减
					if T.surplusTime < 0 {
						T.surplusTime = T.Time // * 还原周期
						// * 触发处理
						go T.Call()
					}
				}
			}
			<-lock
		}
	}()
}
